﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace DroneLib.Communication
{
    public class TcpStream : MavStream
    {
        //public IPAddress LocalIP { get; set; } = IPAddress.Any;
        //public int LocalPort { get; set; } = 5760;
        public IPAddress RemoteIP { get; set; }
        public int RemotePort { get; set; }

        TcpClient _Client = null;
        NetworkStream _Ns = null;
        public override long Length => _Client == null ? 0 : (_Client.Available);

        public override bool Connected=>_Client==null?false:_Client.Connected;

        public TcpStream()
        {

        }

        //public TcpStream(int locallPort)
        //{
        //    LocalPort = locallPort;
        //}

        public TcpStream(IPAddress remoteIP, int remotePort = 5760)
        {
            RemoteIP = remoteIP;
            RemotePort = remotePort;
        }

        public override void Close()
        {
            IsOpen = false;
            if (_Client != null)
            {
                _Client.Close();
                _Client.Dispose();
                _Client = null;
            }
        }

        public override void Flush()
        {
            if (IsOpen == false)
                return;

            _Ns.Flush();
        }

        bool _Connecting = false;
        public override void Open()
        {
            if (_Connecting)
                return;

            _Connecting = true;
            var client = new TcpClient();
            client.BeginConnect(RemoteIP, RemotePort, TcpConnected, client);
        }

        public override void Reconnect()
        {
            if(_Client!=null)
            {
                _Client.Close();
                _Client.Dispose();
                _Client = null;
            }

            Open();
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            if (IsOpen == false)
                return -1;

            return _Ns.Read(buffer, offset, count);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if (IsOpen == false)
                return;

            _Ns.Write(buffer, offset, count);
        }

        private void TcpConnected(IAsyncResult ia)
        {
            TcpClient client = ia.AsyncState as TcpClient;
            try
            {
                client.EndConnect(ia);
            }
            catch(Exception ex)
            {
                Error=ex.Message;
            }
            if(client.Connected)
            {
                _Client = client;
                _Ns = client.GetStream();
                StartMessageLoop();
                IsOpen = true;
                _Name = $"TCP://{RemoteIP}:{RemotePort}";
                RaiseLinkConnectedEvent(true);
            }
            else
            {
                IsOpen = false;
                ConnectionFailed = true;
                RaiseLinkConnectedEvent(false);
            }

            _Connecting = false;
        }
    }
}
